/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.wuliqing.android.zte.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.util.Log;

import com.wuliqing.android.zte.myapplication.R;

/**
 * Utilities related to loading/saving contact photos.
 *
 */
public class ContactPhotoUtils {
	private static final String TAG = "ContactPhotoUtils";

	public static Uri getResourceUri(int resId, String packageName) {
		return Uri.parse("android.resource://" + packageName + "/" + resId);
	}

	// byte[] --> Bitmap
	public static Bitmap Bytes2Bimap(byte[] b) {
		if (b.length != 0) {
			return BitmapFactory.decodeByteArray(b, 0, b.length);
		} else {
			return null;
		}
	}

	// Bitmap --> byte[]
	public static byte[] Bitmap2Bytes(Bitmap bm) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
		return baos.toByteArray();
	}

	// Bitmap --> Drawable
	public static Drawable bitmap2Drawable(Resources res, Bitmap bitmap) {
		return new BitmapDrawable(res, bitmap);
	}

	// Drawable --> Bitmap
	public static Bitmap drawable2Bitmap(Resources res, int resid) {
		return BitmapFactory.decodeResource(res, resid);
	}

	// Drawable --> Bitmap
	public static Bitmap drawable2Bitmap(Drawable drawable) {
		if (drawable instanceof BitmapDrawable) {
			return ((BitmapDrawable) drawable).getBitmap();
		} else if (drawable instanceof NinePatchDrawable) {
			Bitmap bitmap = Bitmap
					.createBitmap(
							drawable.getIntrinsicWidth(),
							drawable.getIntrinsicHeight(),
							drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
									: Bitmap.Config.RGB_565);
			Canvas canvas = new Canvas(bitmap);
			drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
					drawable.getIntrinsicHeight());
			drawable.draw(canvas);
			return bitmap;
		} else {
			return null;
		}
	}

	private static final String PHOTO_DATE_FORMAT = "'IMG'_yyyyMMdd_HHmmss";

	/**
	 * Generate a new, unique file to be used as an out-of-band communication
	 * channel, since hi-res Bitmaps are too big to serialize into a Bundle.
	 * This file will be passed (as a uri) to other activities (such as the gallery/camera/
	 *  cropper/etc.), and read by us once they are finished writing it.
	 */
	public static Uri generateTempImageUri(Context context) {
		final String  fileProviderAuthority = context.getResources().getString(
				R.string.photo_file_provider_authority);
		return FileProvider.getUriForFile(context, fileProviderAuthority,
				new File(pathForTempPhoto(context, generateTempPhotoFileName())));
	}

	public static Uri generateTempCroppedImageUri(Context context) {
		final String  fileProviderAuthority = context.getResources().getString(
				R.string.photo_file_provider_authority);
		return FileProvider.getUriForFile(context, fileProviderAuthority,
				new File(pathForTempPhoto(context, generateTempCroppedPhotoFileName())));
	}

	private static String pathForTempPhoto(Context context, String fileName) {
		final File dir = context.getCacheDir();
		dir.mkdirs();
		final File f = new File(dir, fileName);
		return f.getAbsolutePath();
	}

	private static String generateTempPhotoFileName() {
		final Date date = new Date(System.currentTimeMillis());
		SimpleDateFormat dateFormat = new SimpleDateFormat(PHOTO_DATE_FORMAT, Locale.US);
		return "ContactPhoto-" + dateFormat.format(date) + ".jpg";
	}

	private static String generateTempCroppedPhotoFileName() {
		final Date date = new Date(System.currentTimeMillis());
		SimpleDateFormat dateFormat = new SimpleDateFormat(PHOTO_DATE_FORMAT, Locale.US);
		return "ContactPhoto-" + dateFormat.format(date) + "-cropped.jpg";
	}

	/**
	 * Given a uri pointing to a bitmap, reads it into a bitmap and returns it.
	 * 
	 * @throws FileNotFoundException
	 */
	public static Bitmap getBitmapFromUri(Context context, Uri uri)
			throws FileNotFoundException {
		final InputStream imageStream = context.getContentResolver()
				.openInputStream(uri);
		try {
			return BitmapFactory.decodeStream(imageStream);
		} finally {
			// Closeables.closeQuietly(imageStream);
			try {
				imageStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * Creates a byte[] containing the PNG-compressed bitmap, or null if
	 * something goes wrong.
	 */
	public static byte[] compressBitmap(Bitmap bitmap) {
		final int size = bitmap.getWidth() * bitmap.getHeight() * 4;
		final ByteArrayOutputStream out = new ByteArrayOutputStream(size);
		try {
			bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
			out.flush();
			out.close();
			return out.toByteArray();
		} catch (IOException e) {
			Log.w(TAG, "Unable to serialize photo: " + e.toString());
			return null;
		}
	}

	public static void addCropExtras(Intent intent, int photoSize) {
		intent.putExtra("crop", "true");
		intent.putExtra("scale", true);
		intent.putExtra("scaleUpIfNeeded", true);
		intent.putExtra("aspectX", 1);
		intent.putExtra("aspectY", 1);
		intent.putExtra("outputX", photoSize);
		intent.putExtra("outputY", photoSize);
	}

	/**
	 * Adds common extras to gallery intents.
	 *
	 * @param intent
	 *            The intent to add extras to.
	 * @param photoUri
	 *            The uri of the file to save the image to.
	 */
	public static void addPhotoPickerExtras(Intent intent, Uri photoUri) {
		intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
		intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
				| Intent.FLAG_GRANT_READ_URI_PERMISSION);
		intent.setClipData(ClipData
				.newRawUri(MediaStore.EXTRA_OUTPUT, photoUri));
	}

	/**
	 * Given an input photo stored in a uri, save it to a destination uri
	 */
	public static boolean savePhotoFromUriToUri(Context context, Uri inputUri,
			Uri outputUri, boolean deleteAfterSave) {
		FileOutputStream outputStream = null;
		InputStream inputStream = null;
		try {
			outputStream = context.getContentResolver()
					.openAssetFileDescriptor(outputUri, "rw")
					.createOutputStream();
			inputStream = context.getContentResolver()
					.openInputStream(inputUri);

			final byte[] buffer = new byte[16 * 1024];
			int length;
			int totalLength = 0;
			while ((length = inputStream.read(buffer)) > 0) {
				outputStream.write(buffer, 0, length);
				totalLength += length;
			}
			Log.v(TAG,
					"Wrote " + totalLength + " bytes for photo "
							+ inputUri.toString());
		} catch (IOException e) {
			Log.e(TAG, "Failed to write photo: " + inputUri.toString()
					+ " because: " + e);
			return false;
		} finally {
			try {
				inputStream.close();
				outputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// Closeables.closeQuietly(inputStream);
			// Closeables.closeQuietly(outputStream);
			if (deleteAfterSave) {
				context.getContentResolver().delete(inputUri, null, null);
			}
		}
		return true;
	}
}
